---
title: 视图
description: View 视图
sidebar_position: 12
---

## 定义
视图（虚拟表），本身是不具有数据的，它是 SQL 中的一个重要概念。

视图的创建连接了一个或多个数据表，不同的查询应用都可以建立在虚拟表之上。


![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250921133053.png)

视图一方面可以帮我们使用表的一部分而不是所有的表，另一方面可以针对不同的用户制定不同的查询视图。

## 创建、更新和删除视图
视图作为虚拟表，封装了底层与数据表的接口，它相当于是一张表或多张表的数据结果集。

因为这一特点，视图可以简化复杂的 SQL 查询，在编写视图之后，可以直接使用它，而不需要考虑视图中包含的基础查询的细节。同时，也可以根据需要更改数据格式，返回与底层数据表格式不同的数据。

:::tip
通常情况下，小型项目中可以不使用视图，但是在大型项目中，以及数据表比较复杂的情况下，视图的价值就凸显出来了，它可以帮助我们把经常查询的结果集放到虚拟表中，提升查询效率。
:::
### CREATE VIEW
```sql
CREATE VIEW view_name AS
 SELECT column1, column2, ...
 FROM table_name
 WHERE condition;
```
其实就是在查询语句的基础上封装了 VIEW，这样会基于 SQL 语句的结果集形成一张虚拟表。其中 view_name 为视图名称，column1, column2, ... 为视图中的字段，table_name 为基础表，condition 为查询条件。

以 NBA 球员为例，查询比 NBA 球员平均身高高的球员都有那些，显示他们的 ID 和身高。给这个视图起个名字 player_above_avg_height ,那么创建视图可以写成：
```sql
CREATE VIEW player_above_avg_height AS
SELECT player_id, height
FROM players
WHERE height > (SELECT AVG(height) FROM players);
```
当视图创建后，它就相当于一个虚拟表，可以直接使用
```sql
SELECT * FROM player_above_avg_height;
```
### 嵌套视图
当创建好一张视图之后，还可以在它的基础上继续创建视图，比如 player_above_avg_height 的基础上，找到比这个表中的球员平均身高高的球员，作为新的视图 player_above_avg_height_2， 那么可以写成：
```sql
CREATE VIEW player_above_avg_height_2 AS
SELECT player_id, height
FROM player_above_avg_height
WHERE height > (SELECT AVG(height) FROM player_above_avg_height);
```
### ALTER VIEW
修改视图的语法是：
```sql
ALTER VIEW view_name AS
 SELECT column1, column2, ...
 FROM table_name
 WHERE condition;
```
修改视图的语法和创建视图一样，只是对原有视图的更新。比如，要修改 player_above_avg_height ，增加一个新字段，可以写成：
```sql
ALTER VIEW player_above_avg_height AS
SELECT player_id, height, weight
FROM players
WHERE height > (SELECT AVG(height) FROM players);
```
下次在对视图进行查询的，视图结果会更新。
### DROP VIEW
删除视图的语法是：
```sql
DROP VIEW view_name;
```
删除刚刚创建的视图，可以写成：
```sql
DROP VIEW player_above_avg_height;
```
## 使用视图简化 SQL 操作
视图其实就是对 SELECT 语句进行了封装，方便重用它们。
### 使用视图完成复杂的连接

有两张表， 分别为 player 和 height_grades。 其中 height_grades 记录了不同身高对应的身高等级。这里可以通过创建视图，来完成球员以及对应身高等级的查询。

首先，对 player 表和 height_grades 表进行连接，关联条件是球员的身高 height(在身高等级表规定的最低身高和最高身高之间)，这样就可以得到这个球员对应的身高等级，对应的字段为 height_level。
然后通过 SELECT 得到想要查询的字段，分别为 player_name、height、height_level。 然后把查询结果放在视图 player_height_grades 中：
```sql
CREATE VIEW player_height_grades AS
SELECT player_name, height, height_level
FROM players
JOIN height_grades ON height >= min_height AND height <= max_height;
```
以后进行查询的时候，就可以直接通过视图查询，比如像查询身高介于 180cm 到 190cm 的球员，可以写成：
```sql
SELECT * FROM player_height_grades
WHERE height >= 180 AND height <= 190;
```
这样就把一个相对复杂的连接查询转化成了视图查询。

### 使用视图对数据格式化
如果经常需要输出某个格式的内容，比如想输出球员姓名和对应的球队，对应格式为 player_name(team_name), 那么就可以使用视图来完成数据格式化的操作：
```sql
CREATE VIEW player_team AS
SELECT CONCAT（player_name, '(', team_name, ')') AS player_team
FROM players
JOIN teams ON players.team_id = teams.team_id;
```
首先将 player 表和 team 表进行连接，关联条件是相同的 team_id。想要的格式使用 concat 函数，将player_name 和 team_name 连接起来，并加上括号，得到 player_team。

这样就可以查询到格式化之后的结果了
```sql
SELECT * FROM player_team;
```
### 使用视图与计算字段
在数据查询中，有很多统计的需求可以通过视图来完成。

以球员比赛成绩表为例，对应的表是 player_score 表，一种有 19 个字段，代表的含义如下：


![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250921145207.png)

如果我想要统计每位球员在每场比赛中的二分球、三分球和罚球的得分，可以通过创建视图完成：
```sql
CREATE VIEW game_player_score AS
SELECT game_id,
    player_id,
    (shoot_hits-shoot_3_hits)*2 AS shoot_2_points,
    shoot_3_hits*3 AS shoot_3_points,
    shoot_p_hits AS shoot_p_points,
    score
FROM player_score
```
然后就可以查询每位球员在每场比赛中的得分了：
```sql
SELECT * FROM game_player_score;
```
正确使用视图可以简化复杂的 SQL 查询，让 SQL 更加清爽易用。不过，视图是虚拟表，它只是封装了底层的数据查询接口，因此有些 RDBMS 不支持对视图创建索引。

## 总结
使用视图有很多好处，比如安全、简单清晰。
1. 安全性： 虚拟表是基于底层数据表的，在使用视图时，一般不会轻易通过试图对底层数据进行修改，即便是单表视图，也会受到限制，比如计算字段、类型转换等是无法通过视图来对底层数据进行修改的，这也在一定程度上保证了数据表的数据安全性。同时，还可以针对不同用户开放不同的数据查询权限。
2. 简单清晰：视图是对 SQL 查询的封装，它可以将原本复杂的 SQL 查询简化，在编写好查询之后，就可以直接重用而不必直到基本的查询细节。同时还可以在视图之上再嵌套视图。

视图是虚拟表，本身并不存储数据，只能用于查询，是对 SQL 查询的一种封装。

和临时表不同，临时表是真实存在的数据表，不过它不用于长期存放数据，只为当前连接存在，连接关闭后，临时表就会自动释放。

![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250921163459.png)
